/**
 * @brief 4.1.1 关于表达式的一些基本概念
 */

int main(int argc, char const *argv[])
{
    // 作用于一个运算对象的运算符是一元运算符，如取地址符（&）和解引用符（*）；

    // 运算对象转换
    // 整数能转换成浮点数，浮点数也能转换成整数，但是指针不能转换成浮点数。
    // 小整数类型（如bool、char、short等）通常会被提升（promoted）成较大的整数类型，主要是int。

    // **********************  左值和右值（重中之重！！！！！！！） **********************
    /**
     * 百度百科：
     * 左值可以表示对象，即具有对应的可以由用户访问的存储单元。正因为如此，用于取得对象的指针的内建操作符&要求操作数是左值。
     * 左值表示存储在计算机内存的对象，与此相对的概念是右值(rvalue)。
     * 
     * C语言中：左值可以位于赋值语句的左侧，右值则不能。
     * 然而在C++语言中，左值和右值的区别就没那么简单了。
     * 可以做一个简单的归纳：当一个对象被用作右值的时候，用的是对象的值（内容）；
     * 当对象被用作左值的时候，用的是对象的身份（在内存中的位置）。
     * 
     * 一个重要的原则（参见13.6节，第470页将介绍一种例外的情况）是在需要右值的地方可以用左值来代替
     * 但是不能把右值当成左值（也就是位置）使用。
     * 当一个左值被当成右值使用时，实际使用的是它的内容（值）。
     */

    /**
     * 指针也是一个对象，只不过指针存储了所指对象的地址。
     * 那么既然这样的话，根据百度百科关于左值的定义”左值表示存储在计算机内存的对象，与此相对的概念是右值(rvalue)。“，
     * 岂不是说明指针就是左值？因为指针也是存储在计算机内存中的对象呀！难道不是左值吗？为什么书中说这个指针是一个右值呢？
     * */
    // 哦，我似乎明白了，这句话的意思是不是单独说取地址符和操作数的结果是一个右值？也就是下面这段代码：
    int i = 0; // i是左值
    &i; // &i代表取i对象的地址，返回指向该对象的指针，这个指针是个右值（因为它没有用一个变量存储起来，所以用户访问不到它，是这样吗？）
    int *p = &i; // p这个指针指向了i这个整型对象，p是个左值，而&i是个右值。对吗？

    /**
     * 使用关键字decltype（参见2.5.3节，第62页）的时候，左值和右值也有所不同。
     * 如果表达式的求值结果是左值，decltype作用于该表达式（不是变量）得到一个引用类型。
     * 举个例子，假定p的类型是int＊，因为解引用运算符生成左值，所以decltype（＊p）的结果是int&。
     * 另一方面，因为取地址运算符生成右值，所以decltype（&p）的结果是int＊＊，也就是说，结果是一个指向整型指针的指针。 
     */
    decltype(*p) a = i;  // a是个int&的引用
    decltype(&p) b = &p; // b是个int**的引用，所谓int**就是说b是个指针，它指向一个int*的指针（即指针的指针）

    return 0;
}
